!
! Procedures for handling of a dynamical (linked) list
!
! 
!  Copyright © 2011 F.Hroch (hroch@physics.muni.cz)
!
!  This file is part of Munipack.
!
!  Munipack is free software: you can redistribute it and/or modify
!  it under the terms of the GNU General Public License as published by
!  the Free Software Foundation, either version 3 of the License, or
!  (at your option) any later version.
!  
!  Munipack is distributed in the hope that it will be useful,
!  but WITHOUT ANY WARRANTY; without even the implied warranty of
!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!  GNU General Public License for more details.
!  
!  You should have received a copy of the GNU General Public License
!  along with Munipack.  If not, see <http://www.gnu.org/licenses/>.
!

Module LibList

  ! Item type:
  implicit none
  
  type ImageType
     integer :: i
     real :: skymod,skysig,exptime,temp
     real,  pointer :: image(:,:)
     character(len=80) :: dateobs, filter
     type( ImageType ), pointer :: next
  end type ImageType

contains !---------------------------------------------------------------

  subroutine InitList(list)

    ! Initialize a new list
    ! 
    ! Input: 
    !       nx, ny .. dimension of an image 
    !
    ! Output:
    !
    !        array .. created image
    !        istat .. status

    implicit none
    type(Imagetype), pointer :: list

    nullify(list)
    Allocate(list)
    nullify(list%next)
    list%i = 0

  end subroutine InitList

  Subroutine DestroyList(list)

    implicit none
    type(Imagetype), pointer :: list,c,d

    c => list%next
    do while (associated(c))
       d => c
       c => c%next
       if( associated(d%image) ) deallocate(d%image)
       deallocate(d)
    end do
    deallocate(list)
    nullify(list)

  end Subroutine DestroyList

  !-------------------------------------------------------------------------
  
  Subroutine AddItem (current,array,skymod,skysig,dateobs,exptime,filter,temp)

    ! Initialize a new list
    ! 
    ! Input: 
    !       nx, ny .. dimension of an image 
    !
    ! Output:
    !
    !        array .. created image
    !        istat .. status

    implicit none
    type(Imagetype), pointer :: current
    real, dimension(:,:), optional, pointer :: array
    real, optional, intent(in) :: skymod, skysig, exptime, temp
    character(len=*), optional, intent(in) :: dateobs, filter
    integer :: i

    i = current%i + 1
    Allocate( current%next )
    nullify( current%next%next )
    current => current%next
    current%i = i
    if( present(array) ) then
       current%image => array
    else
       nullify(current%image)
    end if
    if( present(skymod) ) current%skymod = skymod
    if( present(skysig) ) current%skysig = skysig
    if( present(dateobs) ) current%dateobs = dateobs
    if( present(filter) ) current%filter = filter
    if( present(exptime) ) current%exptime = exptime
    if( present(temp) ) current%temp = temp

  end subroutine AddItem

  ! -----------------------------------------------------------------------
  
  subroutine GetItem(current,array,skymod,skysig,dateobs,exptime,filter,temp)

    implicit none
    type(Imagetype) :: current
    real, dimension(:,:), optional, pointer :: array
    real, optional, intent(out) :: skymod,skysig,exptime,temp
    character(len=*), optional, intent(out) :: dateobs,filter

    if( present(array) ) array => current%image
    if( present(skymod) ) skymod = current%skymod
    if( present(skysig) ) skysig = current%skysig
    if( present(dateobs) ) dateobs = current%dateobs
    if( present(exptime) ) exptime = current%exptime
    if( present(filter) ) filter = current%filter
    if( present(temp) ) temp = current%temp


  end subroutine GetItem

  ! ------------------------------------------------------------------------


  Subroutine GetImage(first, n, array)

    ! Get image from list
    !
    ! Input:
    !       n ... Number of image
    !
    ! Output:
    !      array .. image
    
    implicit none
    type(Imagetype), pointer :: first, current
    integer, intent(in) :: n
    real, dimension(:,:), pointer :: array

    current => first
    do while ( associated( current ))
       if( current%i == n ) then
          array => current%image
          return
       endif
       current => current%next
    enddo

  end subroutine GetImage

  !----------------------------------------------------------------------

  Subroutine PutImage( first, n, array, istat)

    ! Put image to list
    !
    ! Input:
    !       n ... Number of image
    !       array .. image
    !

    implicit none
    type(Imagetype), pointer :: first, current
    integer, intent(in) :: n
    integer, intent(inout) :: istat
    real, dimension(:,:), pointer :: array

    if( istat /= 0 ) return

    istat = 11

    current => first
    do while ( associated( current ))
       if( current%i == n ) then
          current%image => array
          return
       endif
       current => current%next
    enddo

  end subroutine PutImage
  
  ! ---------------------------------------------------------------------

  function GetNext(current)

    implicit none
    type(Imagetype), pointer :: current, GetNext

    GetNext => current%next

  end function GetNext
  

  ! ----------------------------------------------------------------------

  function GetNo(current)

    implicit none
    type(Imagetype) :: current
    integer :: getno

    getno = current%i

  end function GetNo
    
  ! -----------------------------------------------------------------------

  subroutine GetSky(current, skymod, skysig)

    implicit none
    type(Imagetype) :: current
    real, intent(out) :: skymod, skysig

    skymod = current%skymod
    skysig = current%skysig
  
  end subroutine GetSky

  ! ---------------------------------------------------------------------

  Subroutine GetPar ( first, n, skymod, skysig, istat)
    
    ! Get parameters 
    !
    ! Input:
    !       n ... Number of image
    !
    ! Output:
    !      skymod, skysig .. parameters
    
    implicit none
    type(Imagetype),pointer :: first, current
    integer, intent(in) :: n
    integer, intent(inout) :: istat
    real, intent(out) :: skymod, skysig

    if( istat /= 0 ) return

    istat = 20

    current => first
    do while ( associated( current ))
       if( current%i == n ) then
          skymod = current%skymod
          skysig = current%skysig
          istat = 0
          return
       endif
       current => current%next
    enddo
    
  end subroutine GetPar

  ! ------------------------------------------------------------------------
  
  Subroutine PutPar (first, n, skymod, skysig, istat)

    ! Put parameters 
    !
    ! Input:
    !       n ... Number of image
    !
    ! Output:
    !      skymod, skysig .. parameters
    
    implicit none
    type(Imagetype),pointer :: first, current
    integer, intent(in) :: n
    integer, intent(inout) :: istat
    real, intent(in) :: skymod, skysig
    
    if( istat /= 0 ) return

    istat = 21
    current => first
    do while ( associated( current ))
       if( current%i == n ) then
          current%skymod = skymod
          current%skysig = skysig
          istat = 0
          return
       endif
       current => current%next
    enddo

  end subroutine PutPar

end module LibList



